package com.achievement.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.achievement.domain.dto.PaperAuthorDTO;
import com.achievement.domain.dto.PaperDTO;
import com.achievement.domain.entity.PaperEntity;
import com.achievement.domain.entity.PaperLevelEntity;
import com.achievement.domain.param.PaperParam;
import com.achievement.domain.vo.PaperAuthorVO;
import com.achievement.domain.vo.PaperVO;
import com.achievement.mapper.PaperMapper;
import com.achievement.mappings.paper.PaperMapping;
import com.achievement.service.IPaperAuthorService;
import com.achievement.service.IPaperLevelService;
import com.achievement.service.IPaperService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.api.ApprovalApi;
import com.common.api.CommonFileApi;
import com.common.core.domain.AjaxResult;
import com.common.utils.DateUtils;
import com.common.utils.QueryWrapperUtils;
import com.common.utils.SecurityUtils;
import com.common.utils.StringUtils;
import com.common.utils.bean.BizProcessMessages;
import com.flowable.domain.vo.task.BpmTaskApproveReqVO;
import com.flowable.service.IFlowTaskService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author CNKI
* @description 针对表【biz_paper(科研成果-学术论文-论文列表)】的数据库操作Service实现
* @createDate 2025-02-12 10:02:32
*/
@Service
public class PaperServiceImpl extends ServiceImpl<PaperMapper, PaperEntity> implements IPaperService {

    @Autowired
    private PaperMapping mapping;

    @Autowired
    private IPaperAuthorService paperAuthorService;

    @Autowired
    private IPaperLevelService paperLevelService;

    @Autowired
    private ApprovalApi approvalApi;

    //流程引擎
    @Autowired
    private IFlowTaskService flowTaskService;

    //通用文件api
    @Autowired
    private CommonFileApi fileApi;

    private final static String module_name = "学术论文";

    /**
     * 列表检索
     *
     * @param param PaperParam
     */
    @Override
    public List<PaperVO> selectByPage(PaperParam param) {

        param.setPublishDateStart(DateUtils.dateStrHandle(param.getPublishDateStart(), param.getDateFormat(), "start"));
        param.setPublishDateEnd(DateUtils.dateStrHandle(param.getPublishDateEnd(), param.getDateFormat(), "end"));

        LambdaQueryWrapper<PaperEntity> queryWrapper = new LambdaQueryWrapper();
        QueryWrapperUtils.getParams_achievement(queryWrapper, SecurityUtils.getLoginUser().getUser());

        List<PaperVO> paperVOList = this.baseMapper.getList(param,queryWrapper);

        //获取当前用户所有的代办列表
        Map<String, String> instanceTaskMap = approvalApi.getInstanceTaskMap(module_name);

        paperVOList.stream().forEach(a -> {
            // 判断是否是审核人，并设置taskId
            String processInstanceId = a.getProcessInstanceId();
            if (StringUtils.isNotEmpty(processInstanceId) && instanceTaskMap.containsKey(processInstanceId)) {
                a.setTaskId(instanceTaskMap.get(processInstanceId));
                a.setIsAuditor(true);
            } else {
                a.setIsAuditor(false);
            }
        });

        return paperVOList;
    }

    /**
     * 论文导出
     *
     * @param param PaperParam
     */
    @Override
    public List<PaperVO> selectByExport(PaperParam param) {

        param.setPublishDateStart(DateUtils.dateStrHandle(param.getPublishDateStart(), param.getDateFormat(), "start"));
        param.setPublishDateEnd(DateUtils.dateStrHandle(param.getPublishDateEnd(), param.getDateFormat(), "end"));

        LambdaQueryWrapper<PaperEntity> queryWrapper = new LambdaQueryWrapper();
        QueryWrapperUtils.getParams_achievement(queryWrapper, SecurityUtils.getLoginUser().getUser());

        List<PaperVO> paperVOList = this.baseMapper.getListByExport(param,queryWrapper);

        //设置刊物级别名称
        for (PaperVO paperVO : paperVOList) {
            String paperLevelId = paperVO.getPaperLevelId();
            List<String> list = Arrays.asList(paperLevelId.split(","));

            //设置刊物级别名称
            List<PaperLevelEntity> paperLevelEntities = paperLevelService.listByIds(list);
            String paperLevelNames = paperLevelEntities.stream().map(PaperLevelEntity::getName).collect(Collectors.joining(";"
            ));
            paperVO.setPaperLevelId(paperLevelNames);

            String embodyTypeId = paperVO.getEmbodyTypeId();
            List<String> embodyIds = Arrays.asList(embodyTypeId.split(","));

            //设置收录类别名称
            List<PaperLevelEntity> embodyTypeEntities = paperLevelService.listByIds(embodyIds);
            String embodyTypeNames =
                    embodyTypeEntities.stream().map(PaperLevelEntity::getName).collect(Collectors.joining(";"
            ));
            paperVO.setEmbodyTypeId(embodyTypeNames);


        }

        return paperVOList;
    }


    /**
     * 获取论文详细信息
     *
     * @param id id
     */
    @Override
    public PaperVO getInfoById(String id) {


        PaperEntity entity = this.getById(id);
        if (ObjectUtil.isNull(entity)){
            return new PaperVO();
        }

        PaperVO paperVO = mapping.entity2Vo(entity);
        //文件名
        String fileName = fileApi.getFileName(paperVO.getFileIds());
        paperVO.setFileNames(fileName);

        paperVO.setPaperLevelIdList(Arrays.asList(entity.getPaperLevelId().split(",")));
        paperVO.setEmbodyTypeIdList(Arrays.asList(entity.getEmbodyTypeId().split(",")));

        //查询论文作者列表信息
        List<PaperAuthorVO> authorVOList = paperAuthorService.getInfoByPaperId(id);

        paperVO.setAuthorList(authorVOList);

        //获取当前用户所有的代办列表
        Map<String, String> instanceTaskMap = approvalApi.getInstanceTaskMap(module_name);
        // 判断是否是审核人，并设置taskId
        String processInstanceId = paperVO.getProcessInstanceId();
        if (StringUtils.isNotEmpty(processInstanceId) && instanceTaskMap.containsKey(processInstanceId)) {
            paperVO.setTaskId(instanceTaskMap.get(processInstanceId));
            paperVO.setIsAuditor(true);
        } else {
            paperVO.setIsAuditor(false);
        }



        return paperVO;
    }

    /**
     * 新增论文
     *
     * @param dto PaperDTO
     */
    @Override
    public AjaxResult add(PaperDTO dto) {

        String UUID = IdUtil.randomUUID().replace("-", "");

        dto.setId(UUID);

        List<PaperAuthorDTO> authorList = dto.getAuthorList();

        String authorpids = authorList.stream().map(PaperAuthorDTO::getPersonId).collect(Collectors.joining(","));
        String authorunitids = authorList.stream().map(PaperAuthorDTO::getAuthorUnitId).collect(Collectors.joining(";"));

        dto.setAuthorpids(authorpids);
        dto.setAuthorunitids(authorunitids);
        dto.setAuthorNumber(authorList.size());

        //第一作者
        List<PaperAuthorDTO> firstAuthros =
                authorList.stream().filter(a -> a.getAuthorType().equals("0") || a.getAuthorType().equals("1") || a.getAuthorType().equals("4")).collect(Collectors.toList());
        //通讯作者
        List<PaperAuthorDTO> txAuthors =
                authorList.stream().filter(a -> a.getAuthorType().equals("2") || a.getAuthorType().equals("4") || a.getAuthorType().equals("5")).collect(Collectors.toList());


        String firstAuthorNames = firstAuthros.stream().map(PaperAuthorDTO::getAuthorName).collect(Collectors.joining(";"));
        String txAuthorNames = txAuthors.stream().map(PaperAuthorDTO::getAuthorName).collect(Collectors.joining(";"));


        //新增论文基本信息
        PaperEntity entity = mapping.dto2Entity(dto);

        entity.setFirstAuthorName(firstAuthorNames);
        entity.setTxAuthorName(txAuthorNames);

        entity.setPaperLevelId(StrUtil.join(",",dto.getPaperLevelIdList()));
        entity.setEmbodyTypeId(StrUtil.join(",",dto.getEmbodyTypeIdList()));


        //新增论文作者信息
        //根据论文 paperId，删除作者信息，再新增作者信息
        paperAuthorService.deleteByPaperId(UUID);

        //给每个作者加上论文ID
        for (PaperAuthorDTO paperAuthorDTO : dto.getAuthorList()) {
            paperAuthorDTO.setPaperId(UUID);
        }

        Integer submitType = dto.getSubmitType();

        switch (submitType) {
            case 2: // 保存并通过
                entity.setProcessInstanceId("0");
                entity.setCheckstatus(String.valueOf(submitType));
                entity.setCheckdate(DateUtils.getTime());
                entity.setChecker(SecurityUtils.getNickName());
                break;
            case 1: // 提交
                entity.setCheckstatus(String.valueOf(submitType));
                if (!(this.save(entity) && paperAuthorService.add(dto.getAuthorList()))) {
                    return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                }
                String processInstanceId = null;
                try {
                    //发起流程 业务状态由流程引擎更新
                    processInstanceId = approvalApi.businessEntryApproval(entity.getId(), module_name);
                } catch (Exception e) {
                    AjaxResult.error(BizProcessMessages.SAVE_PARTIAL_SUCCESS);
                }

                return StringUtils.isEmpty(processInstanceId)
                        ? AjaxResult.error(BizProcessMessages.SAVE_PARTIAL_SUCCESS)
                        : AjaxResult.success((Object)entity.getId());
            default: // 处理 -1（暂存）及其他情况
                entity.setCheckstatus(String.valueOf(submitType));
                break;
        }

        boolean r = this.save(entity)
                && paperAuthorService.add(dto.getAuthorList());
        return r ? AjaxResult.success((Object)entity.getId()) : AjaxResult.error(BizProcessMessages.SAVE_FAIL);
    }

    /**
     * 修改论文
     *
     * @param dto PaperDTO
     */
    @Override
    public AjaxResult update(PaperDTO dto) {

        List<PaperAuthorDTO> authorList = dto.getAuthorList();

        //处理旧文件

        String id = dto.getId();
        PaperEntity oldPaperEntity = this.getById(id);
        String newFileId = dto.getFileIds();
        String oldFileId = oldPaperEntity.getFileIds();
        //替换了文件
        if (StringUtils.isNotEmpty(oldFileId) && StringUtils.isNotEmpty(newFileId) && !newFileId.equals(oldFileId)){
            fileApi.delFile(oldFileId);
            //文件从有到无
        } else if (StringUtils.isNotEmpty(oldFileId) && StringUtils.isEmpty(newFileId)) {
            fileApi.delFile(oldFileId);
        }

        String authorpids = authorList.stream().map(a -> a.getPersonId()).collect(Collectors.joining(","));
        String authorunitids = authorList.stream().map(a -> a.getAuthorUnitId()).collect(Collectors.joining(";"));

        dto.setAuthorpids(authorpids);
        dto.setAuthorunitids(authorunitids);
        dto.setAuthorNumber(authorList.size());

        PaperEntity entity = mapping.dto2Entity(dto);

        entity.setPaperLevelId(StrUtil.join(",",dto.getPaperLevelIdList()));
        entity.setEmbodyTypeId(StrUtil.join(",",dto.getEmbodyTypeIdList()));

        //第一作者
        List<PaperAuthorDTO> firstAuthros =
                authorList.stream().filter(a -> a.getAuthorType().equals("0") || a.getAuthorType().equals("1") || a.getAuthorType().equals("4")).collect(Collectors.toList());
        //通讯作者
        List<PaperAuthorDTO> txAuthors =
                authorList.stream().filter(a -> a.getAuthorType().equals("2") || a.getAuthorType().equals("4") || a.getAuthorType().equals("5")).collect(Collectors.toList());


        String firstAuthorNames = firstAuthros.stream().map(PaperAuthorDTO::getAuthorName).collect(Collectors.joining(";"));
        String txAuthorNames = txAuthors.stream().map(PaperAuthorDTO::getAuthorName).collect(Collectors.joining(";"));

        entity.setFirstAuthorName(firstAuthorNames);
        entity.setTxAuthorName(txAuthorNames);



        //新增论文作者信息
        //根据论文 paperId，删除作者信息，再新增作者信息
        paperAuthorService.deleteByPaperId(entity.getId());

        //给每个作者加上论文ID
        for (PaperAuthorDTO paperAuthorDTO : dto.getAuthorList()) {
            paperAuthorDTO.setPaperId(entity.getId());
        }


        Integer submitType = dto.getSubmitType();

        switch (submitType) {
            case 2: // 保存并通过
                // 当前用户是否是审批人
                boolean isAuditor = dto.getIsAuditor();
                // 审批人直接审核（仅适用于提交类型2且为当前审核人的情况）
                if (isAuditor) {
                    if (this.updateById(entity)&& paperAuthorService.add(dto.getAuthorList())) {
                        BpmTaskApproveReqVO bta = new BpmTaskApproveReqVO();
                        bta.setId(dto.getTaskId());
                        bta.setReason(SecurityUtils.getNickName() + "保存并通过");
                        try {
                            flowTaskService.approveTask(SecurityUtils.getUserId(), bta);
                        } catch (Exception e) {
                            return AjaxResult.error(BizProcessMessages.SAVE_SUCCESS_APPROVE_FAIL, e.getMessage());
                        }

                        return AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
                    }
                    return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                }
                //处理非当前审批人保存并通过
                if (!dto.getCheckstatus().equals("2")){
                    entity.setProcessInstanceId("0");
                }
                entity.setCheckdate(DateUtils.getTime());
                entity.setChecker(SecurityUtils.getNickName());
                //只有管理员才会有非当前审核人的情况下有 "保存并提交"按钮,审核完后的结果只能是审核通过
                entity.setCheckstatus(String.valueOf(submitType));
                break;
            case 1:
                //暂存转提交
                if (!(this.updateById(entity)&& paperAuthorService.add(dto.getAuthorList()))) {
                    return AjaxResult.error(BizProcessMessages.SAVE_FAIL);
                }
                String returnProcessInstanceId = null;
                try {
                    returnProcessInstanceId = approvalApi.businessEntryApproval(entity.getId(), module_name);
                } catch (Exception e) {
                    return AjaxResult.error(BizProcessMessages.SAVE_PARTIAL_SUCCESS, e.getMessage());
                }

                return StringUtils.isEmpty(returnProcessInstanceId)
                        ? AjaxResult.warn(BizProcessMessages.SAVE_PARTIAL_SUCCESS)
                        : AjaxResult.success(BizProcessMessages.SAVE_SUCCESS);
            case -1: // 暂存
                return this.updateById(entity) && paperAuthorService.add(dto.getAuthorList())
                        ? AjaxResult.success(BizProcessMessages.SAVE_SUCCESS)
                        : AjaxResult.error(BizProcessMessages.SAVE_FAIL);
            default:
                break;
        }

        return this.updateById(entity) && paperAuthorService.add(dto.getAuthorList())
                ? AjaxResult.success(BizProcessMessages.SAVE_SUCCESS)
                : AjaxResult.error(BizProcessMessages.SAVE_FAIL);

    }

    /**
     * 左上方统计 通过，退回，待审核
     *
     * @param param param
     */
    @Override
    public List<HashMap<String, Integer>> listStatistics(PaperParam param) {

        param.setPublishDateStart(DateUtils.dateStrHandle(param.getPublishDateStart(), param.getDateFormat(), "start"));
        param.setPublishDateEnd(DateUtils.dateStrHandle(param.getPublishDateEnd(), param.getDateFormat(), "end"));

        LambdaQueryWrapper<PaperEntity> queryWrapper = new LambdaQueryWrapper();
        QueryWrapperUtils.getParams_achievement(queryWrapper, SecurityUtils.getLoginUser().getUser());

        return this.baseMapper.listStatistics(param,queryWrapper);
    }

    /**
     * 删除论文
     *
     * @param ids ids
     */
    @Override
    public boolean batchRemove(List<String> ids) {

        //删除作者
        paperAuthorService.deleteByPaperIdList(ids);
        for (String id: ids) {
            PaperEntity paper = this.getById(id);
            if (paper !=null && StringUtils.isNotEmpty(paper.getFileIds())){
                try {
                    fileApi.delFile(paper.getFileIds());
                } catch (Exception e) {
                    log.error("删除文件失败，fileId：" + id, e);
                }
            }
        }

        return this.removeByIds(ids);
    }

    @Override
    public void updateBusinessStatus(String tableName, String businessId, String checkStatus, String sysUserId) {
        if (StringUtils.isEmpty(tableName) || StringUtils.isEmpty(businessId) || StringUtils.isEmpty(checkStatus))
            return;
        PaperEntity entity = new PaperEntity();
        entity.setId(businessId);
        entity.setCheckstatus(checkStatus);
        if ("2".equals(checkStatus)) {
            entity.setCheckdate(DateUtils.getTime());
            entity.setChecker(SecurityUtils.getNickName());
        }
        this.updateById(entity);
    }
}




